#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import http.server
import socketserver
import json
import urllib.parse
from urllib.parse import urlparse, parse_qs
import webbrowser
import os
import requests
import pandas as pd
from datetime import datetime, timedelta
import mimetypes

# 聚合数据API配置
JUHE_FLIGHT_APPKEY = "b0daee5c7cf963ae6458020601583575"

# 城市到IATA机场代码映射
CITY_TO_IATA = {
    '大连': 'DLC', '北京': 'PEK', '上海': 'PVG', '广州': 'CAN',
    '深圳': 'SZX', '成都': 'CTU', '重庆': 'CKG', '西安': 'XIY',
    '武汉': 'WUH', '南京': 'NKG', '杭州': 'HGH', '天津': 'TSN',
    '青岛': 'TAO', '厦门': 'XMN', '长沙': 'CSX', '郑州': 'CGO',
    '合肥': 'HFE', '济南': 'TNA', '福州': 'FOC', '南昌': 'KHN',
    '石家庄': 'SJW', '太原': 'TYN', '呼和浩特': 'HET', '沈阳': 'SHE',
    '长春': 'CGQ', '哈尔滨': 'HRB', '昆明': 'KMG', '贵阳': 'KWE',
    '南宁': 'NNG', '海口': 'HAK', '三亚': 'SYX', '兰州': 'LHW',
    '西宁': 'XNN', '银川': 'INC', '乌鲁木齐': 'URC', '拉萨': 'LXA'
}

# 周边城市映射
NEARBY_CITIES = {
    '大连': ['沈阳', '营口', '丹东', '鞍山'],
    '合肥': ['南京', '武汉', '郑州', '济南'],
    '北京': ['天津', '石家庄', '保定', '廊坊'],
    '上海': ['南京', '杭州', '苏州', '无锡'],
    '广州': ['深圳', '佛山', '东莞', '中山'],
    '深圳': ['广州', '东莞', '惠州', '佛山']
}

# 生成示例高铁数据
def generate_sample_train_data():
    """生成示例高铁数据"""
    return [
        {
            'type': 'train',
            'train_number': 'G1234',
            'train_type': '高铁',
            'origin': '大连',
            'destination': '合肥',
            'dep_time': '2025-09-20 08:30',
            'arr_time': '2025-09-20 16:45',
            'price': 580,
            'dep_station': '大连北站',
            'arr_station': '合肥南站',
            'duration': '8小时15分',
            'seat_type': '二等座',
            'is_high_speed': '是',
            'source': '示例数据',
            'crawl_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        },
        {
            'type': 'train',
            'train_number': 'G5678',
            'train_type': '高铁',
            'origin': '大连',
            'destination': '合肥',
            'dep_time': '2025-09-20 14:20',
            'arr_time': '2025-09-20 22:35',
            'price': 620,
            'dep_station': '大连北站',
            'arr_station': '合肥南站',
            'duration': '8小时15分',
            'seat_type': '二等座',
            'is_high_speed': '是',
            'source': '示例数据',
            'crawl_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        }
    ]

def calculate_duration(dep_time, arr_time):
    """计算行程时间"""
    try:
        if dep_time and arr_time:
            if len(dep_time) == 5:  # HH:MM格式
                dep = datetime.strptime(dep_time, '%H:%M')
                arr = datetime.strptime(arr_time, '%H:%M')
            else:  # 完整日期时间格式
                dep = datetime.strptime(str(dep_time), '%Y-%m-%d %H:%M')
                arr = datetime.strptime(str(arr_time), '%Y-%m-%d %H:%M')
            
            duration = arr - dep
            hours = duration.seconds // 3600
            minutes = (duration.seconds % 3600) // 60
            
            if hours > 0:
                return f"{hours}小时{minutes}分" if minutes > 0 else f"{hours}小时"
            else:
                return f"{minutes}分钟"
    except Exception as e:
        print(f"❌ 计算时间异常: {e}")
    return "未知"

def get_flight_data(origin, destination, date):
    """获取机票数据"""
    try:
        dep_code = CITY_TO_IATA.get(origin, origin)
        arr_code = CITY_TO_IATA.get(destination, destination)
        
        url = "https://apis.juhe.cn/flight/query"
        params = {
            'key': JUHE_FLIGHT_APPKEY,
            'dtype': 'json',
            'departure': dep_code,
            'arrival': arr_code,
            'departureDate': date
        }
        
        print(f"📡 机票API请求: {url}")
        print(f"📋 参数: {params}")
        
        response = requests.get(url, params=params, timeout=15)
        print(f"📊 响应状态: {response.status_code}")
        
        if response.status_code == 200:
            result = response.json()
            print(f"📋 响应数据: {json.dumps(result, ensure_ascii=False)[:200]}...")
            
            if result.get('error_code') == 0:
                flights = []
                flight_list = result.get('result', {}).get('flightInfo', [])
                
                for item in flight_list:
                    try:
                        flight = {
                            'type': 'flight',
                            'flight_number': item.get('flightNo', ''),
                            'airline': item.get('airlineName', ''),
                            'origin': origin,
                            'destination': destination,
                            'dep_time': f"{item.get('departureDate', '')} {item.get('departureTime', '')}",
                            'arr_time': f"{item.get('arrivalDate', '')} {item.get('arrivalTime', '')}",
                            'price': int(item.get('ticketPrice', 0)),
                            'dep_airport': item.get('departureName', ''),
                            'arr_airport': item.get('arrivalName', ''),
                            'duration': calculate_duration(item.get('departureTime', ''), item.get('arrivalTime', '')),
                            'source': '聚合数据API',
                            'crawl_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                        }
                        
                        if flight['price'] > 0:
                            flights.append(flight)
                            
                    except Exception as e:
                        print(f"  ❌ 解析航班条目异常: {e}")
                        continue
                
                print(f"✅ 获取到 {len(flights)} 条机票数据")
                return flights
            else:
                print(f"❌ 机票API错误: {result.get('reason', '未知')}")
                return []
        else:
            print(f"❌ 机票API请求失败: {response.status_code}")
            return []
            
    except Exception as e:
        print(f"❌ 机票API异常: {e}")
        return []

class MyHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        path = urlparse(self.path).path
        
        # 处理根路径重定向
        if path == '/':
            self.send_response(302)
            self.send_header('Location', '/frontend/index.html')
            self.end_headers()
            return
        
        # 处理API请求
        if path.startswith('/api/'):
            self.handle_api_request(path)
            return
        
        # 处理静态文件
        if path.startswith('/frontend/'):
            self.serve_static_file(path)
            return
        
        # 其他请求返回404
        self.send_error(404)
    
    def do_POST(self):
        path = urlparse(self.path).path
        
        if not path.startswith('/api/'):
            self.send_error(404)
            return
        
        content_length = int(self.headers.get('Content-Length', 0))
        post_data = self.rfile.read(content_length)
        
        try:
            data = json.loads(post_data.decode('utf-8'))
        except:
            data = {}
        
        if path == '/api/search':
            self.send_search_result(data)
        else:
            self.send_error(404)
    
    def handle_api_request(self, path):
        """处理API请求"""
        if path == '/api/status':
            self.send_api_status()
        elif path == '/api/cities':
            self.send_cities()
        elif path == '/api/test':
            self.send_test_response()
        else:
            self.send_error(404)
    
    def serve_static_file(self, path):
        """提供静态文件服务"""
        # 移除 /frontend/ 前缀
        file_path = path[9:]  # 移除 '/frontend/'
        
        # 安全检查：防止路径遍历攻击
        if '..' in file_path:
            self.send_error(403)
            return
        
        # 构建完整文件路径
        full_path = os.path.join('frontend', file_path)
        
        print(f"🔍 请求文件: {path} -> {full_path}")
        
        try:
            # 检查文件是否存在
            if not os.path.exists(full_path):
                self.send_error(404)
                return
            
            # 获取MIME类型
            mime_type, _ = mimetypes.guess_type(full_path)
            if mime_type is None:
                mime_type = 'application/octet-stream'
            
            # 读取文件内容
            with open(full_path, 'rb') as f:
                content = f.read()
            
            # 发送响应
            self.send_response(200)
            self.send_header('Content-type', mime_type)
            self.send_header('Content-Length', str(len(content)))
            self.end_headers()
            self.wfile.write(content)
            
        except Exception as e:
            print(f"❌ 文件服务异常: {e}")
            self.send_error(500)
    
    def send_api_status(self):
        status = {
            'success': True,
            'status': 'success',
            'message': '完整版服务器运行正常',
            'version': '4.0.0',
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'features': [
                '真实机票数据获取（聚合数据API）',
                '示例高铁数据',
                '周边城市智能对比',
                '智能排序和推荐',
                '完整静态文件服务'
            ],
            'apis': {
                'flight': 'enabled',
                'train': 'enabled (示例数据)',
                'nearby': 'enabled',
                'smart_sort': 'enabled'
            },
            'nearby_cities': NEARBY_CITIES
        }
        self.send_json_response(status)
    
    def send_cities(self):
        cities = list(NEARBY_CITIES.keys())
        self.send_json_response({'success': True, 'cities': cities})
    
    def send_test_response(self):
        self.send_json_response({
            'success': True,
            'message': '完整版服务器测试成功',
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        })
    
    def send_search_result(self, data):
        origin = data.get('origin', '北京')
        destination = data.get('destination', '上海')
        date = data.get('date') or data.get('departure_date')
        optimization_type = data.get('optimization_type', 'time')
        
        print(f"🔍 搜索请求: {origin} → {destination} ({date})")
        
        all_routes = []
        
        # 1) 获取机票数据
        flights = get_flight_data(origin, destination, date or '2025-09-20')
        all_routes.extend(flights)
        
        # 2) 获取高铁数据
        trains = generate_sample_train_data()
        # 筛选匹配的高铁数据
        filtered_trains = []
        for train in trains:
            if (train['origin'] == origin and train['destination'] == destination):
                filtered_trains.append(train)
        all_routes.extend(filtered_trains)
        
        # 3) 周边城市数据
        nearby_origins = NEARBY_CITIES.get(origin, [])
        nearby_destinations = NEARBY_CITIES.get(destination, [])
        
        # 周边出发城市
        for nearby_origin in nearby_origins[:2]:
            nearby_flights = get_flight_data(nearby_origin, destination, date or '2025-09-20')
            for flight in nearby_flights:
                flight['is_nearby'] = True
                flight['nearby_type'] = 'origin'
                flight['nearby_city'] = nearby_origin
                flight['origin'] = f"{nearby_origin}({origin}附近)"
            all_routes.extend(nearby_flights)
        
        # 周边到达城市
        for nearby_dest in nearby_destinations[:2]:
            nearby_flights = get_flight_data(origin, nearby_dest, date or '2025-09-20')
            for flight in nearby_flights:
                flight['is_nearby'] = True
                flight['nearby_type'] = 'destination'
                flight['nearby_city'] = nearby_dest
                flight['destination'] = f"{nearby_dest}({destination}附近)"
            all_routes.extend(nearby_flights)
        
        # 4) 智能排序
        if optimization_type == 'price':
            all_routes.sort(key=lambda x: x.get('price', 0))
        elif optimization_type == 'time':
            all_routes.sort(key=lambda x: x.get('dep_time', ''))
        else:  # comprehensive
            # 综合排序：价格权重60%，时间权重40%
            for route in all_routes:
                price_score = 1000 - route.get('price', 0)
                time_score = 50  # 默认时间分数
                nearby_penalty = -50 if route.get('is_nearby', False) else 0
                route['smart_score'] = price_score * 0.6 + time_score * 0.4 + nearby_penalty
            
            all_routes.sort(key=lambda x: x.get('smart_score', 0), reverse=True)
        
        # 优先显示非周边城市的结果
        all_routes.sort(key=lambda x: x.get('is_nearby', False))
        
        # 统计信息
        flights_count = len([x for x in all_routes if x.get('type') == 'flight'])
        trains_count = len([x for x in all_routes if x.get('type') == 'train'])
        nearby_count = len([x for x in all_routes if x.get('is_nearby', False)])
        
        result = {
            'success': True,
            'routes': all_routes,  # 前端期望routes字段
            'data': all_routes,    # 保持兼容性
            'total': len(all_routes),
            'flights': flights_count,
            'trains': trains_count,
            'nearby': nearby_count,
            'optimization_type': optimization_type,
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        }
        
        print(f"✅ 搜索完成: 找到 {len(all_routes)} 条结果（航班 {flights_count}，火车 {trains_count}，周边 {nearby_count}）")
        self.send_json_response(result)
    
    def send_json_response(self, data):
        self.send_response(200)
        self.send_header('Content-type', 'application/json; charset=utf-8')
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
        self.send_header('Access-Control-Allow-Headers', 'Content-Type')
        self.end_headers()
        
        json_data = json.dumps(data, ensure_ascii=False, indent=2)
        self.wfile.write(json_data.encode('utf-8'))

if __name__ == '__main__':
    PORT = 5000
    
    print("=" * 60)
    print("启动完整版HTTP服务器")
    print("=" * 60)
    print(f"服务地址: http://localhost:{PORT}")
    print(f"测试地址: http://localhost:{PORT}/api/test")
    print(f"城市列表: http://localhost:{PORT}/api/cities")
    print(f"前端页面: http://localhost:{PORT}/frontend/index.html")
    print("=" * 60)
    print("按 Ctrl+C 停止服务")
    print("=" * 60)
    
    try:
        # 自动打开浏览器到前端页面
        try:
            webbrowser.open(f"http://localhost:{PORT}/frontend/index.html")
        except Exception:
            pass
        with socketserver.TCPServer(("", PORT), MyHTTPRequestHandler) as httpd:
            httpd.serve_forever()
    except KeyboardInterrupt:
        print("\n服务器已停止")
    except Exception as e:
        print(f"服务器启动失败: {e}")